package com.feign.util;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class FileUtil {

    private static final String FILE_TYPE = "file";
    private static final String FOLDER_TYPE = "folder";

    /**
     * 获取文件大小 如果是文件那么直接返回该文件的大小，如果是文件夹则返回改文件夹下所有文件的大小
     * @param file 文件
     * @return 文件大小
     */
    public static Long getFileSize(File file) {
        Long totalSize = 0L;
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files == null) return 0L;
            for (File listFile : files) {
                totalSize += getFileSize(listFile);
            }
        } else {
            totalSize += file.length();
        }
        return totalSize;
    }

    /**
     * 查询该路径是否为文件夹
     * @param path 绝对路径
     * @return 文件夹
     * @throws Exception 失败抛出异常提示
     */
    public static File folderExist(String path) throws Exception {
        File file = new File(path);
        if (!file.exists()) throw new Exception("文件夹不存在");
        if (!file.isDirectory()) throw new Exception("不是文件夹");
        return file;
    }

    /**
     * 查询该路径是否为文件
     * @param path 绝对路径
     * @return 文件
     * @throws Exception 失败抛出异常提示
     */
    public static File fileExist(String path) throws Exception {
        File file = new File(path);
        if (!file.exists()) throw new Exception("文件不存在");
        if (!file.isFile()) throw new Exception("不是件夹");
        return file;
    }

    /**
     * 搜索文件
     * @param file 起始目录文件对象
     * @param name 要搜索的文件名称
     * @return 文件集合
     */
    public static List<File> searchFileName(File file, String name) {
        List<File> fileList = FileUtil.searchFileAll(file);
        return fileList.stream().filter(item -> item.getName().toLowerCase().contains(name.toLowerCase())).collect(Collectors.toList());
    }

    /**
     * 查询所有文件
     * @param file 初始文件
     * @return 文件集合
     */
    public static List<File> searchFileAll(File file) {
        List<File> fileList = new ArrayList<>();

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files == null) return new ArrayList<>();
            for (File file1 : files) {
                List<File> fileList1 = FileUtil.searchFileAll(file1);
                fileList.addAll(fileList1);
            }
        }else {
            fileList.add(file);
        }

        return fileList;
    }

    /**
     * 删除文件
     * @param fileList 文件路径集合
     */
    public static void deleteFiles(List<File> fileList){
        for (File file : fileList) {
            if(!file.exists()) continue;

            if(file.isDirectory()){
                List<File> list = Arrays.asList(file.listFiles());
                FileUtil.deleteFiles(list);
            }

            file.delete();
        }
    }

    /**
     * 重命名文件
     * @param oldFile 旧文件
     * @param newFile 新文件
     * @throws Exception
     */
    public static Boolean fileRename(File oldFile, File newFile) throws Exception {
        String newName = newFile.getName().replace(oldFile.getName(), "");
        validFileNameValidation(newName,FILE_TYPE);

        if (!oldFile.exists()) throw new Exception("文件 " + oldFile.getName() + " 不存在");
        if(newFile.exists()) throw new Exception("文件 " + newFile.getName() + " 已存在");
        return oldFile.renameTo(newFile);
    }

    /**
     * 文件名合法校验
     * @param newName 文件名
     * @param type "file" 文件, "folder" 文件夹
     * @throws Exception
     */
    private static void validFileNameValidation(String newName, String type) throws Exception {
        List<String> list = null;
        if(FILE_TYPE.equals(type)){
            list = Arrays.asList("\\", "/", ":", "*", "?", "\"", "<", ">", "|");
        } else if (FOLDER_TYPE.equals(type)) {
            list = Arrays.asList(":", "*", "?", "\"", "<", ">", "|");
        }
        char[] charArray = newName.toCharArray();

        for (char c : charArray) {
            List<String> collect = list.stream().filter(item -> item.contains(String.valueOf(c))).collect(Collectors.toList());
            if(collect.size() > 0){
                StringBuilder sb = new StringBuilder();
                list.forEach(item -> sb.append(item));
                throw new Exception("文件名不能包含下列任何字符 " + sb);
            }
        }
    }

    /**
     * 移动文件
     * @param oldFile 旧文件
     * @param newFile 新文件
     * @throws Exception
     */
    public static Boolean fileMove(File oldFile, File newFile) throws Exception {
        if (!oldFile.exists()) throw new Exception("文件 " + oldFile.getName() + " 不存在");
        if(newFile.exists()) throw new Exception("文件 " + newFile.getName() + " 已存在");
        newFile.getParentFile().mkdirs();
        return oldFile.renameTo(newFile);
    }

    /**
     * 创建文件
     * @param currentPath 当前路径
     * @param fileName 文件名
     * @return
     * @throws Exception
     */
    public static Boolean newFile(String currentPath, String fileName) throws Exception {
        validFileNameValidation(fileName,FOLDER_TYPE);
        File file = new File(currentPath + File.separator + fileName);
        if(!new File(currentPath).exists()) throw new Exception("目录 " + currentPath + " 不存在");
        if (file.exists()) throw new Exception("文件 " + file.getName() + " 已存在");
        return file.createNewFile();
    }

    /**
     * 创建文件夹
     * @param currentPath 当前路径
     * @param folderName 文件夹名称
     * @return
     * @throws Exception
     */
    public static Boolean newFolder(String currentPath, String folderName) throws Exception {
        validFileNameValidation(folderName,FOLDER_TYPE);
        File file = new File(currentPath + File.separator + folderName);
        if (file.exists()) throw new Exception("文件夹 " + file.getName() + " 已存在");
        return file.mkdirs();
    }

    /**
     * 复制文件
     * @param copyFiles 被复制的文件
     * @param copyToPath 保存路径
     * @throws IOException
     */
    public static void copyFile(List<File> copyFiles, String copyToPath) throws IOException {
        for (File file : copyFiles) {
            if (file.isDirectory()) {
                // 处理文件夹
                File newDestinationFolder = new File(copyToPath, file.getName());
                newDestinationFolder.mkdirs(); // 创建目标文件夹
                copyFile(Arrays.asList(file.listFiles()), newDestinationFolder.getAbsolutePath());
            } else {
                // 处理文件
                File file1 = new File(copyToPath + File.separator + file.getName());
                int num = 0;
                while (file1.exists()){
                    num++;
                    String s = (file.getName().contains(".") ? file.getName().substring(0, file.getName().lastIndexOf(".")) : file.getName()) + (num == 0 ? "" :" (" + num + ")") + (file.getName().contains(".") ? file.getName().substring(file.getName().lastIndexOf(".")) : "");
                    file1 = new File(copyToPath,s);
                }
                Files.copy(file.toPath(), file1.toPath());
            }
        }
    }

    /**
     * 获取文件icon
     * @param file 文件
     * @param outputStream 输出流
     * @throws Exception
     */
    public static void fileIcon(File file, OutputStream outputStream) throws Exception {
        if (!file.exists()) throw new Exception("文件不存在");

        FileSystemView fileSystemView = FileSystemView.getFileSystemView();
        Icon systemIcon = fileSystemView.getSystemIcon(file);
        BufferedImage bufferedImage = new BufferedImage(systemIcon.getIconWidth(), systemIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        systemIcon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);

        ImageIO.write(bufferedImage, "PNG", outputStream);
    }

    public static void defaultSort(List<File> list){
        Collections.sort(list, (o1, o2) -> {
            if (o1.isHidden() && !o2.isHidden()) {
                return 1; // 隐藏文件在后
            } else if (!o1.isHidden() && o2.isHidden()) {
                return -1; // 隐藏文件在后
            } else if (o1.isDirectory() && !o2.isDirectory()) {
                return -1; // 文件夹在前
            } else if (!o1.isDirectory() && o2.isDirectory()) {
                return 1; // 文件夹在前
            } else {
                return o1.getName().compareTo(o2.getName());
            }
        });
    }

    public static void main(String[] args) throws Exception {
        List<File> fileList = FileUtil.searchFileName(new File("e:/"), "");
        System.out.println(fileList.size());
    }
}
